package org.wanda.pv;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.impl.FileSqlManager;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;
import org.nutz.dao.util.Daos;
import org.nutz.lang.random.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.wanda.pv.controller.business.ExcelController;
import org.wanda.pv.model.basic.*;
import org.wanda.pv.model.basic.System;
import org.wanda.pv.model.business.Drawing;
import org.wanda.pv.model.business.Mark;
import org.wanda.pv.model.hy.HyTree;
import org.wanda.pv.model.hy.HyUserInfo;

import org.wanda.pv.model.user.SysRole;
import org.wanda.pv.model.user.SysUser;
import org.wanda.pv.service.conver.PDFConverImage;
import org.wanda.pv.service.conver.ToPngProcess;
import org.wanda.pv.service.file.FileUploadService;
import org.wanda.pv.util.HyUtil;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

@EnableAsync
@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true)

@SuppressWarnings("all")
public class WdWebApplication extends SpringBootServletInitializer implements CommandLineRunner,DisposableBean {
	private Logger logger= LoggerFactory.getLogger(this.getClass());
	@Autowired
	private Dao dao;

	@Autowired
	FileUploadService fileUploadService;

	@Autowired
	PDFConverImage pdfConverImage;

	@Autowired
	ToPngProcess toPngProcess;

	/*@Autowired
	private AsynInitDrawing asynInitDrawing;
*/
	public static void main(String[] args) {
		SpringApplication.run(WdWebApplication.class, args);
	}

	/**
	 *
	 * @param args
	 * @throws Exception
	 */
	@Override
	public void run(String... args) throws Exception {
		init();
	}

	@Override
	public void destroy() throws Exception {

	}

	public void init(){
		try{
			Daos.createTablesInPackage(dao,"org.wanda.pv",false);
			Daos.migration(dao,"org.wanda.pv",true,false);
			initTree();
            processQueue();
			try{
				initBasicData();

			}catch (Exception e){
				logger.error(e.getMessage(),e);
			}

			logger.info("\n-----------------------启动完成----------------------");
		}catch (Exception e){

			e.printStackTrace();
		}

	}



	private void processQueue(){


			new Thread(()->{

				while (true){
					try{
						toPngProcess.process(pdfConverImage.toJpgQueue().take());
					}catch (Exception e){
						logger.error(e.getMessage(),e);
					}
				}



			}).start();




	}



	private void initSysUser(){
		if (0==dao.count(SysUser.class)){
			SysUser user = new SysUser();
			String passwd = new BCryptPasswordEncoder().encode("123456");
			user.setLoginname("pvAdmin");
			user.setUsername("三审单位");
			user.setPassword(passwd);
			user = dao.insert(user);
			SysRole role = new SysRole();
			role.setName("三审管理员");
			role.setAliasName("ROLE_PV_ADMIN");
			role=dao.insert(role);
			dao.insert("sys_user_role", Chain.make("user_id",user.getId()).add("role_id",role.getId()));

			user = new SysUser();
			user.setLoginname("deAdmin");
			user.setUsername("设计总包");
			user.setPassword(passwd);
			user = dao.insert(user);
			role = new SysRole();
			role.setName("设计管理员");
			role.setAliasName("ROLE_DE_ADMIN");
			role=dao.insert(role);
			dao.insert("sys_user_role", Chain.make("user_id",user.getId()).add("role_id",role.getId()));

			user = new SysUser();
			user.setLoginname("wdAdmin");
			user.setUsername("万达");
			user.setPassword(passwd);
			user = dao.insert(user);
			role = new SysRole();
			role.setName("万达管理员");
			role.setAliasName("ROLE_WD_ADMIN");
			role=dao.insert(role);
			dao.insert("sys_user_role", Chain.make("user_id",user.getId()).add("role_id",role.getId()));




		}
	}

	private void initUserInfo(){

		if (0==dao.count(HyUserInfo.class)){

			try {
				String access_token = HyUtil.getHyToken().getAccess_token();
				String userSimple = HyUtil.getUserSimple(access_token);
				HyUserInfo userInfo = HyUtil.getUserInfo(userSimple, access_token);
				if (userInfo.getId()!=null){
					dao.insert(userInfo);
				}else{
					FileSqlManager fmq = new FileSqlManager("sqls/hy_user_info.sql");
					List<Sql> sqlListq = fmq.createCombo(fmq.keys());
					sqlListq.stream().forEach(sql -> dao.execute(sql));
				}
			}catch (Exception e){
				logger.error(e.getMessage(),e);
			}


		}

	}
	/**
	 * 判断那个基础数据表没有数据就初始化那个表
	 */
	private void initBasicData() {



		if (0 == dao.count(PointClass.class)) {
			FileSqlManager fmq = new FileSqlManager("sqls/wd_point_class.sql");
			List<Sql> sqlListq = fmq.createCombo(fmq.keys());
			sqlListq.stream().forEach(sql -> dao.execute(sql));
		}
		if (0 == dao.count(Specialty.class)) {
			FileSqlManager fmq = new FileSqlManager("sqls/wd_specialty.sql");
			List<Sql> sqlListq = fmq.createCombo(fmq.keys());
			sqlListq.stream().forEach(sql -> dao.execute(sql));
		}
		if (0 == dao.count(System.class)) {
			FileSqlManager fmq = new FileSqlManager("sqls/wd_system.sql");
			List<Sql> sqlListq = fmq.createCombo(fmq.keys());
			sqlListq.stream().forEach(sql -> dao.execute(sql));
		}

		if(0 == dao.count(PointRoom.class)){
			FileSqlManager fmq = new FileSqlManager("sqls/wd_point_room.sql");
			List<Sql> sqlListq = fmq.createCombo(fmq.keys());
			sqlListq.stream().forEach(sql -> dao.execute(sql));
		}

		if(0 == dao.count(TopPoint.class)){
			try {
				initPoint();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		/*if (0 == dao.count(Point.class)){
			FileSqlManager fmq6 = new FileSqlManager("sqls/wd_point.sql");
			List<Sql> sqlListq6 = fmq6.createCombo(fmq6.keys());
			sqlListq6.stream().forEach(sql -> dao.execute(sql));

			FileSqlManager fmq4 = new FileSqlManager("sqls/wd_re_point_point_room.sql");
			List<Sql> sqlListq4 = fmq4.createCombo(fmq4.keys());
			sqlListq4.stream().forEach(sql -> dao.execute(sql));
			FileSqlManager fmq5 = new FileSqlManager("sqls/wd_re_point_specialty.sql");
			List<Sql> sqlListq5 = fmq5.createCombo(fmq5.keys());
			sqlListq5.stream().forEach(sql -> dao.execute(sql));

		}*/
		if (!hasPointView()){
			FileSqlManager fmq = new FileSqlManager("sqls/view.sql");
			List<Sql> sqlListq = fmq.createCombo(fmq.keys());
			sqlListq.stream().forEach(sql -> dao.execute(sql));
		}


	}

	private boolean hasPointView(){
		Sql sql = Sqls.create("SELECT count(1) count  FROM information_schema.TABLES WHERE table_name = @viewName");
		sql.setParam("viewName","wd_point_info_view");

		sql.setCallback(new SqlCallback() {
			@Override
			public Object invoke(Connection connection, ResultSet rs, Sql sql) throws SQLException {
				List<Integer> counts = new ArrayList<>();
				while (rs.next()){
					int count = rs.getInt("count");
					counts.add(count);
				}

				return counts;
			}
		});
		dao.execute(sql);
		List<Integer> counts = sql.getList(Integer.class);
		int count = counts.get(0);
		if (0==count)
			return false;
		return true;
	}



	/**
	 * 初始化树
	 */
	private void initTree(){
		if(dao.count(HyTree.class)==0){
			String access_token = HyUtil.getHyToken().getAccess_token();
			List<HyTree> tree = HyUtil.getTree(access_token);
			saveTree(tree);
		}


	}



	private void saveTree(List<HyTree> tree) {

		for (HyTree hyTree : tree) {
			dao.insert(hyTree);
			if (hyTree.getChildren().size()>0){
				saveTree(hyTree.getChildren());
			}
		}

	}

	public Object initPoint() throws IOException {
		InputStream resourceAsStream = ExcelController.class.getClassLoader().getResourceAsStream("1-商业项目施工图审查要点-建筑.xlsx");
		//FileInputStream inputStream = new FileInputStream("C:\\Users\\lxy\\Desktop\\1-商业项目施工图审查要点-建筑.xlsx");
		XSSFWorkbook hssfWorkbook = new XSSFWorkbook(resourceAsStream);
		XSSFSheet sheet = hssfWorkbook.getSheetAt(7);
		String systemName = "";
		for (int i = 4; i < sheet.getLastRowNum(); i++) {
			XSSFRow row = sheet.getRow(i);
			XSSFCell cell = row.getCell(0);
			// 判断切换系统
			if (!"".equals(cell.getStringCellValue()) && cell.getStringCellValue().contains("、")) {
				StringBuilder builder = new StringBuilder();
				String [] splitName = cell.getStringCellValue().split("、");
				for (int o = 0; o< splitName.length; o++ ) {
					if(o >0){
						if (o + 1 < splitName.length){
							builder = builder.append(splitName[o]+"、") ;
						} else {
							builder = builder.append(splitName[o]) ;
						}
					}
				}
				systemName = builder.toString();
			}
			// 这个条件下都是子要点,判断有没有小数点，区分是审查内容还是问题类别小计
			row = sheet.getRow(i);
			cell = row.getCell(1);
			String  serialNumber = "";
			XSSFCell cell2 = row.getCell(2);
			XSSFCell cell3 = row.getCell(3);
			if (cell.getCellType() == 1) {
				row.getCell(0).setCellType(Cell.CELL_TYPE_NUMERIC);
				serialNumber = cell.getStringCellValue() ;
			} else {
				serialNumber = String.valueOf(cell.getNumericCellValue() );
			}
			serialNumber = serialNumber.trim();
			if (serialNumber.contains(".") && !cell2.getStringCellValue().isEmpty() && !serialNumber.startsWith("0.0")) {
				java.lang.System.out.println(serialNumber+ " " + cell2.getStringCellValue() + " " + cell3.getStringCellValue());
				addData(systemName,serialNumber,cell2.getStringCellValue(),cell3.getStringCellValue());
			}
		}
		return "ok";
	}

	public void  addData(String systemName,String serialNumber,String content,String pointClassName){
		System system =null;
		// 如果部位分项为空，就不添加
		if (!"".equals(systemName) && systemName != null){
			system = dao.fetch(System.class,Cnd.where("system_name","=",systemName));
			dao.fetchLinks(system,"specialty");
		}
		// 有要点等级的是普通要点
		if (!"".equals(pointClassName) && pointClassName != null){
			Point point = new Point();
			point.setName(content);
			if (system != null){
				point.setSystemId(system.getId());
			}
			PointClass pointClass = dao.fetch(PointClass.class,Cnd.where("point_class_name","=",pointClassName));
			if (pointClass != null){
				point.setPointClassId(pointClass.getId());
			}
			String number = serialNumber.substring(0,3);
			TopPoint topPoint = dao.fetch(TopPoint.class,Cnd.where("number","=",number));
			if (topPoint != null){
				point.setTopPointId(topPoint.getId());
			}
			point.setNumber(serialNumber);
			point =  dao.insert(point);
			dao.insert("wd_re_point_specialty", Chain.make("point_id",point.getId()).add("specialty_id",system.getSpecialtyId()));
		} else {
			TopPoint topPoint =new TopPoint();
			if (system != null){
				topPoint.setSystemId(system.getId());
				topPoint.setSpecialtyId(system.getSpecialtyId());
			}
			topPoint.setName(content);
			topPoint.setNumber(serialNumber);
			topPoint =  dao.insert(topPoint);
			dao.insert("wd_re_point_specialty", Chain.make("point_id",topPoint.getId()).add("specialty_id",system.getSpecialtyId()));
		}
	}

}



